use std::error::Error;
use spdlog::info;
use tokio::{
    net::TcpListener,
    io::{AsyncRead, AsyncWrite}
};
use tokio::io::AsyncReadExt;
use crate::{
    error::ProxyResult,
    option::ProxyOption
};
use crate::error::ProxyError;

pub struct ProxyServer {
    option: ProxyOption,
}

impl ProxyServer {
    pub fn new(option: ProxyOption) -> ProxyServer {
        ProxyServer { option }
    }

    async fn deal_stream<T> (&self, inbound: T) -> ProxyResult<()>
    where T: AsyncRead + AsyncWrite + Send + Unpin + 'static{

        // 处理数据
        tokio::spawn(async move {
            let (mut reader_client,mut write_client) = tokio::io::split(inbound);
            let mut buf = vec![0u8; 2048];
            loop {
                tokio::select! {
                    // todo
                    n = reader_client.read(&mut buf) => {
                        println!("read {:?}", n);
                        let n = n?;
                        if n == 0 {
                            return Err(ProxyError::ConnectionClosed);
                        } else {
                            info!("{:?}", &buf[..n]);
                        }
                    }
                }
            }
        });

        Ok(())
    }

    pub async fn start(&self) -> Result<(), Box<dyn Error>> {
        let server_addr = format!("{}:{}", self.option.bind_addr, self.option.bind_port);

        let listen = TcpListener::bind(server_addr).await?;

        while let Ok((inbound,_)) = listen.accept().await {
            let _ = self.deal_stream(inbound).unwrap();
        }
        Ok(())
    }
}